// HEAD YieldCurve_NonLinearInterpolatedMethods H
/*==================================================================================================================
                  Copyright (C) 2013 SUMSCOPE L.P.
                  ALL RIGHTS RESERVED 
====================================================================================================================
File description:
    This class is to define Non-Linear Interpolated methods. Add new interpolating methods here.

====================================================================================================================
...Date      Name                                  Description of Change
15-Apr-2013  James Xu                              Initial version
25-Apr-2013  James Xu                              Add Hermite interpolation method
13-May-2013  James Xu                              Restructure this class
03-Jun-2013  James Xu                              Add GetCurvePoints
$HISTORY$
===================================================================================================================*/

#ifndef NONLINEAR_INTERPOLATED_METHODS_H
#define NONLINEAR_INTERPOLATED_METHODS_H

#include <vector>

#include "utility.h"
#include "BondDataStructure.h"

namespace YieldCurve
{

    // ----------------------------------------------------------------------------------------
    // -------------- InterpolatedMethod class- ----------------------------------------
    // ----------------------------------------------------------------------------------------
    class InterpolatedMethod 
    {

    public:
        InterpolatedMethod(const std::vector<double>& x, const std::vector<double>& y);
        InterpolatedMethod(const std::vector<YieldPoints>& knots);

        virtual ~InterpolatedMethod();

        // Get interpolated value of Hermite Curve
        virtual double InterpolatedValue(double x) = 0;

        // Get a vector of interpolated points
        virtual void GetCurvePoints(int count, std::vector<YieldPoints>& points) = 0;

    protected:
        // Compute knot's slope
        virtual void ComputeSlopes(const std::vector<double>& x, const std::vector<double>& y);

    protected:
        std::vector<double> solution_;
        bool calculated_;
        std::vector<double> x_;
        std::vector<double> y_;

    };
    
    // Cubic Hermite Interpolation
    class CubicHermiteInterpolation : public InterpolatedMethod 
    {
    public:
        CubicHermiteInterpolation(const std::vector<double>& x, const std::vector<double>& y);
        CubicHermiteInterpolation(const std::vector<YieldPoints>& knots);

        // Get interpolated value of Hermite Curve at xi
        virtual double InterpolatedValue(double x);

        // Get a vector of interpolated points
        virtual void GetCurvePoints(int count, std::vector<YieldPoints>& points);

    };

    // LocalLinear + Hermite Interpolation
    class LocalLinearHermiteInterpolation : public InterpolatedMethod 
    {
    public:
        LocalLinearHermiteInterpolation(const std::vector<double>& x, const std::vector<double>& y, const std::vector<double>& keyX);
        LocalLinearHermiteInterpolation(const std::vector<YieldPoints>& knots, const std::vector<double>& keyX);

        // Get interpolated value of Hermite Curve
        virtual double InterpolatedValue(double x);

        // Get a vector of interpolated points
        virtual void GetCurvePoints(int count, std::vector<YieldPoints>& points);

    private:
        // Get interpolated value of Curve at x using local linear
        virtual double LLInterpolatedValue(double x) const;

    private:
        std::vector<double> keyX_;
        std::vector<double> keyY_;
    };
}

#endif